<template>
  <span 
    class="transition-number" 
    :style="{ 
      color: textColor,
      '--transition-duration': `${duration}ms`
    }"
  >
    {{ formattedValue }}
  </span>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'

interface Props {
  value: number
  duration?: number
  decimals?: number
  prefix?: string
  suffix?: string
  textColor?: string
}

const props = withDefaults(defineProps<Props>(), {
  duration: 600,
  decimals: 2,
  prefix: '',
  suffix: '',
  textColor: 'inherit'
})

const currentValue = ref(0)
const isTransitioning = ref(false)

// 格式化数字显示
const formattedValue = computed(() => {
  const formatted = currentValue.value.toFixed(props.decimals)
  return `${props.prefix}${formatted}${props.suffix}`
})

// 平滑过渡到新值
const transitionToValue = (newValue: number) => {
  if (Math.abs(newValue - currentValue.value) < 0.01) {
    currentValue.value = newValue
    return
  }

  isTransitioning.value = true
  
  // 使用CSS transition实现平滑过渡
  const startValue = currentValue.value
  const difference = newValue - startValue
  const startTime = performance.now()
  
  const animate = (currentTime: number) => {
    const elapsed = currentTime - startTime
    const progress = Math.min(elapsed / props.duration, 1)
    
    // 使用easeOutQuart缓动函数
    const easedProgress = 1 - Math.pow(1 - progress, 4)
    
    currentValue.value = startValue + (difference * easedProgress)
    
    if (progress < 1) {
      requestAnimationFrame(animate)
    } else {
      currentValue.value = newValue
      isTransitioning.value = false
    }
  }
  
  requestAnimationFrame(animate)
}

// 监听value变化
watch(() => props.value, (newValue, oldValue) => {
  if (oldValue !== undefined && newValue !== oldValue) {
    transitionToValue(newValue)
  } else {
    currentValue.value = newValue
  }
}, { immediate: true })

// 组件挂载时设置初始值
onMounted(() => {
  currentValue.value = props.value
})
</script>

<style scoped>
.transition-number {
  display: inline-block;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  
  /* 使用CSS transition实现颜色过渡 */
  transition: 
    color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
    transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  
  /* 确保数字宽度固定，避免布局跳动 */
  font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Source Code Pro', monospace;
  
  /* 硬件加速，提升渲染性能 */
  transform: translateZ(0);
  will-change: transform;
  
  /* 防止文本选择 */
  user-select: none;
  -webkit-user-select: none;
  
  /* 优化渲染 */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* 过渡状态的视觉反馈 */
.transition-number:not(.transitioning) {
  /* 静态状态下的样式 */
}

/* 响应式优化 */
@media (prefers-reduced-motion: reduce) {
  .transition-number {
    transition: none;
  }
}
</style>
